package com.jl.registermvc;

import com.jl.resolver.ContractRequestBodyArgumentResolver;
import com.jl.resolver.ContractRequestResponseBodyMethodProcessor;
import com.jl.util.ClassUtil;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

import java.util.List;

public class ContractReturnValueWebMvcConfigurer implements BeanFactoryAware, InitializingBean {

    private WebMvcConfigurationSupport webMvcConfigurationSupport;
    private ConfigurableBeanFactory beanFactory;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        if (beanFactory instanceof ConfigurableBeanFactory) {
            this.beanFactory = (ConfigurableBeanFactory) beanFactory;
            this.webMvcConfigurationSupport = beanFactory.getBean(WebMvcConfigurationSupport.class);
        }
    }

    @Override
    public void afterPropertiesSet() {

        if (this.beanFactory == null) {
            throw new IllegalStateException("beanFactory cannot use");
        }
        if (this.webMvcConfigurationSupport == null) {
            throw new IllegalStateException("webMvcConfigurationSupport cannot use");
        }

        try {
            Class<WebMvcConfigurationSupport> configurationSupportClass = WebMvcConfigurationSupport.class;
            List<HttpMessageConverter<?>> messageConverters = ClassUtil.invokeNoParameterMethod(configurationSupportClass, webMvcConfigurationSupport, "getMessageConverters");
            List<HandlerMethodReturnValueHandler> returnValueHandlers = ClassUtil.invokeNoParameterMethod(configurationSupportClass, webMvcConfigurationSupport, "getReturnValueHandlers");
            List<HandlerMethodArgumentResolver> argumentResolverHandlers = ClassUtil.invokeNoParameterMethod(configurationSupportClass, webMvcConfigurationSupport, "getArgumentResolvers");

            //将所有返回值都当作 @ResponseBody 注解进行处理  
            returnValueHandlers.add(new ContractRequestResponseBodyMethodProcessor(messageConverters));


            argumentResolverHandlers.add(new ContractRequestBodyArgumentResolver());
            //因为接口中的注解无法识别，所以需要设置对应的注解 ArgumentResolver
            // 主要为了拿到当前实现类方法，找到interface对应的方法参数。如果interface的方法没有使用springmvc注解，实质没用的。
/**
 argumentResolverHandlers.add(new ContractExpressionValueMethodArgumentResolver(this.beanFactory));
 argumentResolverHandlers.add(new ContractMatrixVariableMapMethodArgumentResolver());
 argumentResolverHandlers.add(new ContractMatrixVariableMethodArgumentResolver());
 argumentResolverHandlers.add(new ContractPathVariableMapMethodArgumentResolver());
 argumentResolverHandlers.add(new ContractPathVariableMethodArgumentResolver());
 argumentResolverHandlers.add(new ContractRequestAttributeMethodArgumentResolver());
 argumentResolverHandlers.add(new ContractRequestHeaderMapMethodArgumentResolver());
 argumentResolverHandlers.add(new ContractRequestHeaderMethodArgumentResolver(this.beanFactory));
 argumentResolverHandlers.add(new ContractRequestParamMapMethodArgumentResolver());
 argumentResolverHandlers.add(new ContractRequestParamMethodArgumentResolver(this.beanFactory, false));
 argumentResolverHandlers.add(new ContractRequestPartMethodArgumentResolver(messageConverters));
 argumentResolverHandlers.add(new ContractRequestResponseBodyMethodProcessor(messageConverters));
 argumentResolverHandlers.add(new ContractServletCookieValueMethodArgumentResolver(this.beanFactory));
 argumentResolverHandlers.add(new ContractServletModelAttributeMethodProcessor(false));
 argumentResolverHandlers.add(new ContractSessionAttributeMethodArgumentResolver());
 **/
        } catch (Exception e) {
            throw new IllegalStateException("Annotation ArgumentResolver add fail");
        }

        //通过反射调用WebMvcConfigurationSupport方法的操作不用担心会消失，因为这几个接口都是 protected 的，所以他们是作为扩展接口来提供的
    }


}
